import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Main {
    static String jarPath = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath();
    static String dirPath = jarPath.substring(0, jarPath.lastIndexOf("/") + 1);

    public static void main(String[] args) {
        if (init())
            return;
        CronUtil.schedule(Config.CRON.get(), new Task() {
            @Override
            public void execute() {
                exec();
            }
        });
        CronUtil.setMatchSecond(true);
        CronUtil.start();
    }

    /**
     * 是否初始化配置文件
     * @return
     */
    public static Boolean init() {
        String path = dirPath + "ddns.setting";
        if (!FileUtil.exist(path)) {
            String str = ResourceUtil.readStr("ddns.setting", Charset.defaultCharset());
            FileWriter fileWriter = new FileWriter(path);
            fileWriter.write(str);
            System.out.println("已生成配置文件，请修改当前目录下ddns.setting文件并重新启动");
            return true;
        }
        return false;
    }

    /**
     * 执行DDNS
     */
    public static void exec() {
        HostAdress host = HostAdress.getHost();
        String ip = "AAAA".equals(Config.TYPE.get()) ? host.getInet6Address() : host.getInet4Address();
        Console.log("{}=>{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")), host);
        JSONObject record = getRecord();
        if (record == null) {
            if (addRecord(ip) == null) {
                Console.log("添加记录失败！");
            } else {
                Console.log("添加记录成功！");
            }
        } else {
            if (Objects.equals(record.getStr("value"), ip)) {
                return;
            } else {
                if (modifyRecord(record.getStr("id"), ip) == null) {
                    Console.log("修改记录失败！");
                } else {
                    Console.log("修改记录成功！");
                }
            }
        }
    }

    /**
     * 合并请求参数
     * @param addParam 待合并参数
     * @return
     */
    public static Map<String, Object> getRequestParam(Map<String, Object> addParam) {
        Map<String, Object> param = new HashMap<>();
        param.put("login_token", String.format("%s,%s", Config.ID.get(), Config.TOKEN.get()));
        param.put("format", "json");
        param.put("lang", "cn");
        param.put("error_on_empty", "no");
        param.put("domain", Config.DOMAIN.get());
        param.put("sub_domain", Config.SUB_DOMAIN.get());
        param.put("record_type", Config.TYPE.get().toUpperCase());
        param.putAll(addParam);
        return param;
    }

    /**
     * 发送请求
     * @param url 请求地址
     * @param param 参数
     * @return
     */
    public static JSON postResult(String url, Map<String, Object> param) {
        String result = HttpUtil.post(url, getRequestParam(param));
        System.out.println(result);
        JSON parse = JSONUtil.parse(result);
        if ("1".equals(parse.getByPath("status.code"))) {
            return parse;
        }
        return null;
    }

    /**
     * 获取记录
     * @return
     */
    public static JSONObject getRecord() {
        System.out.print("获取记录:");
        Map<String, Object> param = new HashMap<>();
        JSON json = postResult("https://dnsapi.cn/Record.List", param);
        if (json == null)
            return null;
        Object records = json.getByPath("records");
        JSONArray array = JSONUtil.parseArray(records);
        if (array.size() > 0)
            return array.getJSONObject(0);
        return null;
    }

    /**
     * 添加记录
     * @param value 记录值
     * @return
     */
    public static JSON addRecord(String value) {
        System.out.print("添加记录:");
        Map<String, Object> param = new HashMap<>();
        param.put("value", value);
        param.put("record_line", "默认");
        return postResult("https://dnsapi.cn/Record.Create", param);
    }

    /**
     * 修改记录
     * @param recordId 记录号
     * @param value 记录值
     * @return
     */
    public static JSON modifyRecord(String recordId, String value) {
        System.out.print("修改记录:");
        Map<String, Object> param = new HashMap<>();
        param.put("record_id", recordId);
        param.put("value", value);
        param.put("record_line", "默认");
        return postResult("https://dnsapi.cn/Record.Modify", param);
    }

}
